package de.cau.apo.problems.binpacking;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import de.cau.apo.problems.IInstance;
import de.cau.apo.utils.InputStreamParser;

/**
 * This class represents an instance of the bin packing problem.
 * There is on the one hand an array of items with different sizes that has 
 * to be packed in as less bins as possible and on the other hand there 
 * is a capacity that must not be exceeded per bin when a bin is filled with items.
 *  
 * @author Tobias Schwede
 */
public class BPInstance implements IInstance {
    
    // ########### properties ###########
    
	/** the capacity each bin has. */
    public int binCapacity = 0;
    /** the array of items that has to be packed in bins */
    public Item[] items = null;
    
    // ########### initialization ###########
    
    /**
     * Default empty constructor.
     */
    public BPInstance() {
    }
    
    // ########### getter/setter ###########
    
    /**
     * @return the capacity each bin has.
     */
    public int getBinCapacity() {
        return this.binCapacity;
    }
    
    /**
     * @return the number of items that has to be packed
     */
    public int getNumberItems() {
        if (this.items == null) {
            return 0;
        }
        return items.length;
    }
    
    /**
     * @return the array of items that has to be packed in bins
     */
    public Item[] getItems() {
		return items;
	}
    
    /**
     * @param index the index of an item
     * @return the item that has the given index
     */
    public Item getItem(int index) {
    	Item item = this.items[index];
    	if (item.getIndex() != index) {
    		for (Item i : this.items) {
    			if (i.getIndex() == index) {
    				return i;
    			}
    		}
    	}
    	return item;
    }
    
    // ########### IInstance implementation ###########
    
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean parseInstance(String instancePath) throws FileNotFoundException {
            FileInputStream in = new FileInputStream(instancePath);
            
        try {
            //the first number is the number of item sizes following this
            int numberItems = InputStreamParser.readNextInt(in);
            if (numberItems == -1) {
                return false;
            }
            
            //the second number is the bin capacity
            this.binCapacity = InputStreamParser.readNextInt(in);
            if (this.binCapacity == -1) {
                this.binCapacity = 0;
                return false;
            }
            this.items = new Item[numberItems];
            
            //read the item sizes
            for (int i = 0;i < numberItems;i++) {
                int size = InputStreamParser.readNextInt(in);
                if (size == -1) {
                    this.binCapacity = 0;
                    this.items = null;
                    return false;
                }
                this.items[i] = new Item(i, size);
            }
            
            in.close();
        } catch (IOException ex) {
            System.err.println(ex.getMessage());
            this.binCapacity = 0;
            this.items = null;
            return false;
        }
        return true;
    }
    
}
